<!--这个页面是登录进来就能看到的页面
    对于管理员：
    管理员登录进来是没有任何数据的，一切为白或0
    管理员可以可以点击右边搜索按钮进行用户查询
    管理员需要提供用户id和该用户设备id
    这边采用了远程搜索从数据库拿取数据进行下拉框提示
    当管理员点击搜索按钮以后先进行所有用户id查询填入用户id远程搜索框里
    接着选好用户id以后又进行一次查询，把该用户名下的设备id和品牌全部查出来插入远程搜索框中
    当两个id都确定以后才能进行数据准确查询
    对于普通用户：
    普通用户无法看见用户id查询框
    当用户点击查询时，自动把该用户id下的设备id和品牌自动查询填入远程搜索框中
    此时只需传入设备id即可，因为普通用户登录时后端已经拿到用户id
    即可实现精准查询-->
<template>
  <div class="all">
    <el-button icon="el-icon-search"
               circle class="admin"
               size="medium"
               @click="handleSearchClick"
               v-if="admin"
    ></el-button>
    <el-drawer
      title="查询"
      :before-close="handleClose"
      :visible.sync="dialog"
      direction="rtl"
      custom-class="demo-drawer"
      ref="drawer"
    >
      <div class="demo-drawer__content">
        <el-form :model="formAdmin">
          <el-form-item  label="用户ID" :label-width="formLabelWidth" v-if="admin">
            <el-select
              v-model="formAdmin.userId"
              filterable
              remote
              reserve-keyword
              placeholder="请输入用户ID"
              :remote-method="userRemoteMethod"
              :loading="loadingUserSearch"
              @change="handleUserIdChange">
              <el-option
                v-for="item in userOptions"
                :key="item.value"
                :label="item.label"
                :disabled="item.disabled"
                :value="item.value"/>
            </el-select>
          </el-form-item>
          <el-form-item  label="设备信息" :label-width="formLabelWidth">
            <el-select
              v-model="formAdmin.device"
              filterable
              remote
              reserve-keyword
              placeholder="请选择设备信息"
              :remote-method="deviceRemoteMethod"
              :loading="loadingSearch">
              <el-option
                v-for="item in deviceOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
        </el-form>
        <div class="demo-drawer__footer" style="display: flex;">
          <el-button type="primary"
                     @click="submitForm"
                     :loading="loadingAdmin"
                     style="width: 50%">
            {{ loadingAdmin ? '提交中 ...' : '确 定' }}
          </el-button>
          <el-button @click="cancelForm" style="width: 50%">取 消</el-button>
        </div>
      </div>
    </el-drawer>
    <div class="base-data">
      <div class="heart">
        <div class="echarts-title-icon">
          <div class="echarts-title">
            <span style="font-size: 12px; font-weight:bold;width: 100%;margin-left: 12%;margin-top: 5% ">心率</span>
            <span style="display: flex; width: 100%; margin-left: 15%;margin-top: 3%">
              <span style="font-size: 18px; font-weight:bold;">{{ averageHeart || 0 }}</span>
              <span style="font-size: 10px; color: gray; margin-left: 5%;margin-top: 6%">次/每分</span>
            </span>
          </div>
          <div class="echarts-icon">
            <img src="../assets/icons/icon-heart.png"
                 style="width: 38px;
                        height: 38px;
                        margin-top: 4%;
                        margin-left: 72%;
                        border-radius: 80%;
                        "
                 alt="">
          </div>
        </div>
        <div class="heart-echarts" id="heart-echarts">
        </div>
      </div>
      <div class="step">
        <div class="echarts-title-icon">
          <div class="echarts-title">
            <span style="font-size: 12px; font-weight:bold;width: 100%;margin-left: 12%;margin-top: 5% ">步数</span>
            <span style="display: flex; width: 100%; margin-left: 15%;margin-top: 3%">
              <span style="font-size: 18px; font-weight:bold;">{{averageStep}}</span>
              <span style="font-size: 10px; color: gray; margin-left: 5%;margin-top: 6%">步</span>
            </span>
          </div>
          <div class="echarts-icon">
            <img src="../assets/icons/icon-walk.png"
                 style="width: 38px;
                        height: 38px;
                        margin-top: 4%;
                        margin-left: 72%;
                        border-radius: 80%;
                        "
             alt="">
          </div>
        </div>
        <div class="heart-echarts" id="step-echarts">
        </div>
      </div>
      <div class="sleep">
        <div class="echarts-title-icon">
          <div class="echarts-title">
            <span style="font-size: 12px; font-weight:bold;width: 100%;margin-left: 12%;margin-top: 5% ">睡眠时长</span>
            <span style="display: flex; width: 100%; margin-left: 15%;margin-top: 3%">
              <span style="font-size: 18px; font-weight:bold;">{{averageSleep}}</span>
              <span style="font-size: 10px; color: gray; margin-left: 5%;margin-top: 6%">小时</span>
            </span>
          </div>
          <div class="echarts-icon">
            <img src="../assets/icons/icon-sleep.png"
                 style="width: 38px;
                        height: 38px;
                        margin-top: 4%;
                        margin-left: 72%;
                        border-radius: 80%;
                        "
             alt="">
          </div>
        </div>
        <div class="heart-echarts" id="sleep-echarts">
        </div>
      </div>
    </div>
    <div class="echarts">
      <div class="health">
        <div class="title-date" >
          <span style="font-size: 18px; font-weight: bold; margin-left: 2%; margin-top: 1%">健康趋势</span>
          <el-col class="date">
            <el-date-picker
              v-model="valueDate"
              type="daterange"
              align="right"
              unlink-panels
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              format="yyyy 年 MM 月 dd 日"
              value-format="yyyy-MM-dd"
              :picker-options="pickerOptions"
              @change="handleDateChange"
            >
            </el-date-picker>
          </el-col>
        </div>
        <div class="all-data" id="all-data"></div>
      </div>
<!--      <div class="target">-->
<!--        <div class="target-span-state">-->
<!--          -->
<!--        </div>-->
<!--      </div>-->
    </div>
    <div class="suggest-action-plan">
      <el-badge :value="warningTableData.length" :hidden="warningTableData.length === 0" class="suggestion">
        <el-table
          :data="warningTableData"
          style="width: 100%; height: 100%; border-radius: 15px;"
          height="100%"
          :header-cell-style="{
      backgroundColor: 'white',
      color: '#000000',
      fontSize: '18px',
      fontWeight: 'bold',
    }"
          :row-style="{height:'15px'}"
        >
          <el-table-column label="警告信息" prop="notifyContent" />
          <el-table-column width="50" v-if="admin">
            <template slot-scope="scope">
              <el-button
                @click="handleSendWarning(scope.$index, scope.row)"
                type="text"
                size="small"
              >发送</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-badge>
      <div class="plan">
        <el-table
          :data="tableData"
          @row-click="handleRowClick"
          style="width: 100%; height: 100%; border-radius: 15px;"
          height="100%"
          :header-cell-style="{
    backgroundColor: 'white',
    color: '#000000',
    fontSize: '18px',
    fontWeight: 'bold',
  }"
          :row-style="{height:'15px'}"
        >
          <el-table-column label="目标计划">
            <template slot-scope="{row}">
              {{
                row.name === '1'
                  ? `步行${row.targetValue}步`
                  : row.name === '2'
                    ? `运动${row.targetValue}小时`
                    : '未知目标类型'
              }}
            </template>
          </el-table-column>

          <el-table-column label="" width="300">
            <template slot-scope="{row}">
              <el-progress
                :percentage="Math.min((parseInt(row.actualValue) / parseInt(row.targetValue) * 100), 100)"
                :color="customColor"
                :stroke-width="20"
                :show-text="false"
              />
              <span style="position: absolute; right: 10px; color: white; font-weight: bold;">
        {{ Math.round((parseInt(row.actualValue) / parseInt(row.targetValue) * 100)) }}%
      </span>
            </template>
          </el-table-column>

          <el-table-column prop="status" align="right">
            <template slot-scope="scope">
      <span :style="{
        color: scope.row.status === '1' ? '#67C23A' : '#F56C6C',
        fontWeight: 'bold'
      }">
        {{ scope.row.status === '1' ? '已完成' : '未完成' }}
      </span>
            </template>
          </el-table-column>
        </el-table>

        <!-- 添加对话框 -->
        <el-dialog
          :visible.sync="dialogVisible"
          title="详细信息"
          width="60%"
          :append-to-body="true"
          :class="{'dialog-animate': dialogVisible}"
        >
          <el-table
            :data="selectedRow ? [selectedRow] : []"
            border
            style="width: 100%"
            class="staggered-table"
          >
            <el-table-column prop="goalId" label="ID" width="120" v-if="admin">
              <template slot-scope="scope">
                <div class="staggered-item">{{ scope.row.goalId }}</div>
              </template>
            </el-table-column>
            <el-table-column prop="name" label="名称">
              <template slot-scope="scope">
                <div class="staggered-item">
                  {{
                    scope.row.name === '1'
                      ? `步行${scope.row.targetValue}步`
                      : scope.row.name === '2'
                        ? `运动${scope.row.targetValue}小时`
                        : '未知目标类型'
                  }}
                </div>
              </template>
            </el-table-column>
            <el-table-column prop="targetValue" label="目标值">
              <template slot-scope="scope">
                <div class="staggered-item">{{ scope.row.targetValue }}</div>
              </template>
            </el-table-column>
            <el-table-column prop="actualValue" label="实际值">
              <template slot-scope="scope">
                  <span class="staggered-item" :style="{color: scope.row.actualValue >= scope.row.targetValue ? '#67C23A' : '#F56C6C',fontWeight: 'bold'}">
                     {{ scope.row.actualValue }}
                  </span>
              </template>
            </el-table-column>
            <el-table-column prop="status" label="状态">
              <template slot-scope="scope">
                  <span class="staggered-item" :style="{color: scope.row.status === '1' ? '#67C23A' : '#F56C6C',fontWeight: 'bold'}">
                     {{ scope.row.status === '1' ? '已完成' : '未完成' }}
                  </span>
              </template>
            </el-table-column>
            <el-table-column prop="date" label="日期">
              <template slot-scope="scope" >
                <div class="staggered-item" >{{ scope.row.date }}</div>
              </template>
            </el-table-column>
          </el-table>
          <div style="margin-top: 10px; padding: 10px; background: #ffffff; border-radius: 4px;" class="staggered-item">
  <span v-if="selectedRow" :style="{color: selectedRow.status === '1' ? '#67C23A' : '#F56C6C', fontWeight: 'bold'}">
    {{ selectedRow.status === '1'
    ? `恭喜完成目标，超出${Math.abs(parseInt(selectedRow.actualValue) - parseInt(selectedRow.targetValue))}，请再接再厉！`
    : `您还未完成目标，还差${Math.abs(parseInt(selectedRow.targetValue) - parseInt(selectedRow.actualValue))}，请继续加油！` }}
  </span>
          </div>
        </el-dialog>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from "echarts";
import {
  createHeartRateSSE,
  listGetAll, listGetDevice, listGetGoal, listGetGoal2,
  listGetSearchClick, listGetWarning, sendEmail
} from '@/api/userData/userData'
import { getInfo } from '@/api/login'

export default {
  name: "User_data",
  data() {
    return {
      //远程搜索框
      userOptions: [],
      loadingUserSearch: false,
      userIdStates:[],
      deviceOptions: [],
      value: [],
      list: [],
      loadingSearch: false,
      deviceStates: [],
      //针对管理员的搜索抽屉
      dialog: false,
      formLabelWidth: '80px',
      loadingAdmin: false,
      echartsAll:[],
      formAdmin: {
        userId: '',
        device:'',
      },
      // 计划表格数据，对象数组，对象里面有图标链接，运动名字，持续时间和多久开始
      warningTableData:[],
      //建议表，对象数组，里面有图标链接，建议标题，建议
      suggestionTableData:[
        {
          iconUrl:require('../assets/icons/icons-dumbbell.png'),
          title:'增加有氧运动',
          content:'建议增加30分钟中等强度运动'
        },{
          iconUrl:require('../assets/icons/icons-dumbbell.png'),
          title:'增加有氧运动',
          content:'建议增加30分钟中等强度运动'
        },{
          iconUrl:require('../assets/icons/icons-dumbbell.png'),
          title:'增加有氧运动',
          content:'建议增加30分钟中等强度运动'
        },{
          iconUrl:require('../assets/icons/icons-dumbbell.png'),
          title:'增加有氧运动',
          content:'建议增加30分钟中等强度运动'
        },
      ],
      progress:0,
      dialogVisible: false,
      selectedRow: null,
      tableData: [],
      //所有数据数组，静态的
      all: {
        date: [],
        heartRate: [],
        steps: [],
        sleepDuration: []
      },
      theAll:[],
      //日期选择器
      pickerOptions: {
        shortcuts: [{
          text: '本周',
          onClick(picker) {
            const end = new Date();
            const start = new Date();
            //如果为星期日,则需要-6,但是getData里面是0,因此需要判断
            const week = start.getDate() - start.getDay() + (start.getDay() === 0 ? -6 : 1);
            start.setDate(week);
            picker.$emit('pick', [start, end]);

          },
        }, {
          text: '最近七天',
          onClick(picker) {
            const end = new Date();
            const start = new Date();
            start.setDate(start.getDate() - 7);
            picker.$emit('pick', [start, end]);
          },
        }, {
          text: '本月',
          onClick(picker) {
            const end = new Date();
            const month = new Date();
            const start = new Date(month.getFullYear(), month.getMonth(), 1);
            picker.$emit('pick', [start, end]);

          }
        }, {
          text: '本年',
          onClick(picker) {
            const end = new Date();
            const start = new Date(new Date().getFullYear(), 0);
            picker.$emit('pick', [start, end]);
          }
        }, {
          text: '最近一年',
          onClick(picker) {
            const end = new Date();
            const start = new Date();
            start.setMonth(start.getMonth() - 12);
            picker.$emit('pick', [start, end]);
          },
        },
        ]
      },
      valueDate: [],
      //睡眠时长数组，用于传参给echarts，
      querySleep: [],
      //步数数组，用于传参给echarts，每分钟更新一次
      queryStep: [],
      //心率数组，用于传参给echarts，每秒收集
      queryHeart: [],
      // 遮罩层
      loading: true,
      //定时器
      intervalId: null,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 用户健康表格数据
      user_dataList: [],
      // 弹出层标题
      title: "",
      //管理员显示?
      admin:"",
      // 是否显示弹出层
      open: false,
      //sse链接
      heartRateSSE: null,
      heartUpdateInterval: null,
      // 查询参数
      queryParams: {
        pageNum: 1,//分页，这个默认
        pageSize: 10,//分页，默认
        userId: null,//userId
        age: null,//年龄
        heartRate: null,//心率
        date: null,//日期
        remark: null,//备注
        steps:null,//步数
        sleepDuration:null,//睡眠时间
        deviceId:null//用户设备Id
      },
    };
  },
  created() {
    this.getIdAndRole()
  },
  mounted() {
    // this.intervalId = setInterval(() => {
    //   this.getHeart(); // 每秒获取心率数据
    //   // 如果需要同时刷新其他数据可以添加：
    //   // this.getStep();
    //   // this.getSleep();
  //   // }, 1000);
  // },
  // beforeDestroy() {
  //   // 清除定时器
  //   if (this.intervalId) {
  //     clearInterval(this.intervalId);
  //     this.intervalId = null;
  //   }
    window.addEventListener('resize', this.onResize);
    //处理远程搜索框数据
    this.deviceOptions = this.deviceStates.map(item => {
      return {
        value: `${item.deviceId} ${item.deviceName} ${item.deviceBrand}`,  // 合并设备名称和品牌
        label: `${item.deviceId} ${item.deviceName} ${item.deviceBrand}`,
      };
    });
  },
  computed: {
    // 均值计算器,增加了对带有单位的数字字符串组合分析
    // 这里需要优化，这里每次拿不到数据，因为页面加载时这个已经开始计算，此时数组里还没有数据，因此没有数据显示，或许把他调成方法？
    averageHeart() {
      // 修正数据源为queryHeart
      if (this.queryHeart.length === 0) return 0;
      // 直接使用数值数组计算（根据SSE推送数据结构调整）
      const sum = this.queryHeart.reduce((acc, num) => acc + num, 0);
      // 使用Math.round替代toFixed保持数值类型
      return Math.round(sum / this.queryHeart.length);
    },
    averageStep() {
      if (this.queryStep.length === 0) return 0;
      const sum = this.queryStep.reduce((acc, num) => acc + num, 0);
      return Math.round(sum / this.queryStep.length);
    },
    averageSleep() {
      if (this.querySleep.length === 0) return 0.0;
      const sum = this.querySleep.reduce((acc, num) => acc + num, 0);
      return Number((sum / this.querySleep.length).toFixed(1));
    }
  },
  methods: {
    //身份验证判断执行方法
    getIdAndRole(){
      getInfo().then(response =>{
        const userId = response.user.userId
        this.admin = response.user.admin
        if(!this.admin){
          this.handleUserIdChange(userId)
          this.queryParams.userId = userId
          this.formAdmin.userId = userId
          this.submitForm()
        }
      })
    },
    //信息警告
    handleSendWarning(index, row) {
      this.warningTableData.splice(index, 1);

      // 添加邮箱验证逻辑
      this.$confirm(`确定发送通知到用户${this.queryParams.userId}的邮箱？`, '发送确认', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        sendEmail(this.queryParams.userId, row.notifyContent)
          .then(() => {
            this.$message.success('发送成功');

            // 添加客户端日志（替代后端日志）
            console.log(`[Client Log] 邮件发送记录:
          用户ID: ${this.queryParams.userId}
          内容: ${row.notifyContent}
          时间: ${new Date().toLocaleString()}`);

          }).catch(error => {
          console.error('发送失败:', error);

          // 添加错误恢复逻辑
          this.warningTableData.splice(index, 0, row);
          this.$message.error(`发送失败: ${error.response?.data?.message || '未知错误'}`);
        });
      }).catch(() => {
        this.$message.info('已取消发送');
        this.warningTableData.splice(index, 0, row); // 恢复删除的行
      });
    },
    //计算完成率，目标计划用
    customColor(percentage) {
      const hue = (percentage/100) * 120;
      return `hsl(${hue}, 100%, 50%)`;
    },
    handleRowClick(row) {
      this.selectedRow = row
      this.dialogVisible = true
    },
    //远程搜索框
    handleUserIdChange(userId) {
      listGetDevice(userId).then(response => {
        // Process device data
        this.deviceStates = response.map(item => ({
          deviceId: item.deviceId,
          deviceName: item.deviceName,
          brand: item.deviceType === '1' ? '华为' : '小米'
        }));

        // Generate search options with no data handling
        this.deviceOptions = this.deviceStates.length > 0
          ? this.deviceStates.map(device => ({
            value: `${device.deviceId} ${device.deviceName} ${device.brand}`,
            label: `${device.deviceId} ${device.deviceName} ${device.brand}`
          }))
          : [{
            value: 'NO_DEVICE',
            label: '该用户暂无设备数据',
            disabled: true
          }];

      }).catch(error => {
        console.error('设备数据获取失败:', error);
        this.$message.error('设备信息加载失败');
        this.deviceOptions = [{
          value: 'ERROR',
          label: '数据加载失败',
          disabled: true
        }];
      });
    },
    userRemoteMethod(query) {
      this.loadingUserSearch = true;
      // 本地过滤逻辑
      // 当原始用户ID数据为空时的处理
      if (this.userIdStates.length === 0) {
        this.userOptions = [{
          value: 'NO_DATA',
          label: '无可用数据',
          disabled: true
        }];
        this.loadingUserSearch = false;
        return;
      }

      // 正常过滤逻辑（不处理无匹配情况）
      this.userOptions = this.userIdStates
        .filter(id => id.includes(query))
        .map(id => ({
          value: id,
          label: id
        }));

      this.loadingUserSearch = false;
    },
    deviceRemoteMethod(query) {
      this.loadingSearch = true;

      // 处理无数据情况
      if (this.deviceStates.length === 0) {
        this.deviceOptions = [{
          value: 'NO_DEVICE',
          label: '该用户暂无设备数据',
          disabled: true
        }];
        this.loadingSearch = false;
        return;
      }

      // 正常过滤逻辑
      this.deviceOptions = this.deviceStates
        .map(item => `${item.deviceId} ${item.deviceName} ${item.brand}`)
        .filter(fullInfo => fullInfo.includes(query))
        .map(info => ({ value: info, label: info }));

      this.loadingSearch = false;
    },
    /** echarts响应式布局*/
    onResize() {
      if (this.chartHeart) {
        this.chartHeart.resize();
      }
      if (this.chartSteps) {
        this.chartSteps.resize();
      }
      if (this.chartSleep) {
        this.chartSleep.resize();
      }
      if (this.chartAll) {
        this.chartAll.resize();
      }
      if (this.chartTarget) {
        this.chartTarget.resize();
      }
    },
    /** 管理员搜索抽屉 这里我们不需要分情况
     * 只要点击这个按钮就向后端发送请求，后端自动检测发送请求的是管理员还是普通用户
     * 若为管理员，则返回所有的普通用户ID
     * 若为普通用户，则返回该用户名下所有设备信息*/
    handleSearchClick() {
      this.dialog = true;
      if(!this.admin){
        return
      }
      listGetSearchClick().then(response => {
        // 修改1：使用Set去重
        const nonAdminIds = [...new Set(
          response.rows
            .filter(user => !user.admin)
            .map(user => user.userId.toString()) // 转换为字符串
        )];

        this.userIdStates = nonAdminIds;

        // 修改2：直接生成可用选项
        this.userOptions = nonAdminIds.length > 0
          ? nonAdminIds.map(id => ({
            value: id,
            label: id // 增加可读前缀
          }))
          : [{
            value: 'NO_USER',
            label: '暂无普通用户',
            disabled: true
          }];

      }).catch(error => {
        console.error('获取用户列表失败:', error);
        this.$message.error('用户数据加载失败');
        // 修改3：错误时设置空状态
        this.userOptions = [{
          value: 'ERROR',
          label: '数据加载失败，请重试',
          disabled: true
        }];
      });
    },
    // 修改handleClose方法保留关闭逻辑
    handleClose(done) {
      this.resetSearchForm();
      done(); // 直接执行关闭
    },
// 新增提交方法
    submitForm() {

      this.loadingAdmin = true;

      this.queryParams.userId = this.formAdmin.userId;

      // 先关闭已有SSE连接
      if (this.heartRateSSE) {
        this.heartRateSSE.eventSource.close();
      }
      // 初始化SSE连接
      this.setupSSEConnection();
      Promise.all([
        this.getAll(),
        this.getGoal(),
        this.getWarning()
      ]).finally(() => {
        this.loadingAdmin = false;
        this.$refs.drawer.closeDrawer();
      });
    },
    cancelForm() {
      this.resetSearchForm();
      this.dialog = false;
    },
    resetSearchForm() {
      if (this.admin){
        this.formAdmin = {
          userId: '',
          device: ''
        };
      }
      this.formAdmin = {
        userId: this.queryParams.userId,
        device: ''
      };
    },
    /** 顶部三个小echarts显示最近心率，步数和睡眠*/
    /**心率——动态，每秒获取一次*/
    initHeart(queryHeart) {
      const heart = document.getElementById('heart-echarts');
      this.chartHeart = echarts.init(heart);
      const option = {
        title: {
          show: queryHeart.length === 0,
          text: '您最近没有数据噢！',
          left: 'center',
          top: 'center',
          textStyle: {
            color: 'grey',
            fontSize: 20
          }
        },
        tooltip: {},
        legend: {
          data: []
        },
        grid: {
          top: 'center',
          bottom: 'center',
          left: 'center',
          right: '20%',
          width: '100%',
          height: '80%'
        },
        xAxis: {
          data: [],
          show: false,
        },
        yAxis: {
          show: false,
        },
        series: [
          {
            name: '心率',
            type: 'line',
            data: queryHeart,
            smooth: true,
            symbol: 'none',
            areaStyle: {
              color: 'rgba(255,0,0,0.32)',
              opacity: 0.5
            },
            lineStyle: {
              color: 'rgba(255,0,0,0.63)'
            }
          }
        ]
      };
      this.chartHeart.setOption(option);
    },
    /**步数——动态每天获取一次，每秒更新一次*/
    initStep(queryStep) {
      const step = document.getElementById('step-echarts');
      this.chartSteps = echarts.init(step);
      const option1 = {
        title: {
          show: queryStep.length === 0,
          text: '您最近没有数据噢！',
          left: 'center',
          top: 'center',
          textStyle: {
            color: 'grey',
            fontSize: 20
          }
        },
        tooltip: {},
        legend: {
          data: []
        },
        grid: {
          top: 'center',
          bottom: 'center',
          left: 'center',
          right: '20%',
          width: '100%',
          height: '80%'
        },
        xAxis: {
          data: [],
          show: false,
        },
        yAxis: {
          show: false,
        },
        series: [
          {
            name: '步数',
            type: 'line',
            data: queryStep,
            smooth: true,
            symbol: 'none',
            areaStyle: {
              color: 'rgba(0,175,255,0.29)',
              opacity: 0.5
            },
            lineStyle: {
              color: 'rgb(0,137,255)'
            }
          }
        ]
      };
      this.chartSteps.setOption(option1);
    },
    /**睡眠——每天获取一次*/
    initSleep(querySleep) {
      const sleep = document.getElementById('sleep-echarts');
      this.chartSleep = echarts.init(sleep);
      const option2 = {
        title: {
          show: querySleep.length === 0,
          text: '您最近没有数据噢！',
          left: 'center',
          top: 'center',
          textStyle: {
            color: 'grey',
            fontSize: 20
          }
        },
        tooltip: {},
        legend: {
          data: []
        },
        grid: {
          top: 'center',
          bottom: 'center',
          left: 'center',
          right: '20%',
          width: '100%',
          height: '80%'
        },
        xAxis: {
          data: [],
          show: false,
        },
        yAxis: {
          show: false,
        },
        series: [
          {
            name: '睡眠时间',
            type: 'line',
            data: querySleep,
            smooth: true,
            symbol: 'none',
            areaStyle: {
              color: 'rgba(130,0,255,0.18)',
              opacity: 0.5
            },
            lineStyle: {
              color: 'rgb(166,0,255)'
            }
          }
        ]
      };
      this.chartSleep.setOption(option2);
    },
    /**中间左边最大的echarts用于显示一段时间的变化趋势——静态*/
    initAll(date, heart, step, sleep) {
      const all = document.getElementById('all-data');
      this.chartAll = echarts.init(all);
      const option3 = {
        tooltip: {},
        legend: {
          data: ['睡眠', '步数', '心率'],
          right: "2%",
        },
        grid: {
          top: '15%',
          bottom: '',
          left: '10%',
          right: '',
          width: '80%',
          height: '70%'
        },
        xAxis: {
          type: 'category',
          // 这个位置的数据应该和日期选择器关联，把日期同时传到这和后端,并且还要分类，例如选择周，那么该数据应该为星期一，星期二之类的；如果是月那就应该显示该月的天数，如果是年那就应该显示12个月
          data: date,
          show:false
        },
        yAxis: {},
        series: [
          {
            name: '睡眠',
            data: sleep,
            type: 'line',
            smooth: true,
            lineStyle: {
              color: 'rgb(166,0,255)'
            },
            itemStyle: {
              color: 'rgb(166,0,255)' // 设置点的颜色为红色
            }
          },
          {
            name: '步数',
            data: step,
            type: 'line',
            smooth: true,
            lineStyle: {
              color: 'rgb(0,137,255)'
            },
            itemStyle: {
              color: 'rgb(0,137,255)' // 设置点的颜色为红色
            }
          },
          {
            name: '心率',
            data: heart,
            type: 'line',
            smooth: true,
            lineStyle: {
              color: 'rgba(255,0,0,0.63)'
            },
            itemStyle: {
              color: 'rgba(255,0,0,0.63)' // 设置点的颜色为红色
            }
          },
        ]
      };
      this.chartAll.setOption(option3);
    },
    /**中间右边的饼图，用于体现用户计划的完成率*/
    /** 获取最近5秒钟内的心率
     * 对于管理员，我们应该没有数据，想要查询应该通过抽屉的查询按钮查询显示；
     * 对于普通用户，我们在登录的时候就有数据，要查数据就要有id，而id在登录的时候在后端已经存在，直接调用即可，不需要前端传递*/
    //在拿取数据以后，我们要先装进数组，然后分配到对应的echarts，和平均值计算
    setupSSEConnection() {
      const maxQuery = 5
      if (!this.queryParams.userId) {
        console.warn('未提供用户ID，SSE连接终止');
        return;
      }
      if (this.heartRateSSE) {
        this.heartRateSSE.eventSource.close();
      }
      this.heartRateSSE = createHeartRateSSE(this.queryParams.userId);

      this.heartRateSSE.onMessage((data) => {

        // 修复逻辑：先判断是否达到最大长度
        if (this.queryHeart.length >= maxQuery) {
          this.queryHeart.shift(); // 当达到5个时，先移除最旧元素
          this.queryStep.shift();
          this.querySleep.shift();
        }
        // 确保只添加一个元素（处理可能的多数据推送）
        const newHeartRate = Number(data[0]?.heartRate); // 取第一个数据点
        const newStep = Number(data[0]?.steps);
        const newSleep = Number(data[0]?.sleepDuration);


        if (!isNaN(newHeartRate)) {
          this.queryHeart.push(newHeartRate);
        }this.initHeart(this.queryHeart);

        if (!isNaN(newStep)) {
          this.queryStep.push(newStep);
        }this.initStep(this.queryStep);

        if (!isNaN(newSleep)) {
          this.querySleep.push(newSleep);
        }this.initSleep(this.querySleep);

      });
      this.heartRateSSE.onError((error) => {
        console.error('SSE连接异常，尝试重连...', error);
        setTimeout(() => this.setupSSEConnection(), 5000);
      });
    },
    /** 获取最近5天内的步数 */
    /** 获取最近5天内的睡眠数据 */
    /** 获取日期范围内的数据
     * 对于管理员，我们不做变化
     * 对于普通用户，我们想登录进去显示默认的从今年1月1日到今天的变化趋势，如果想自行选择就把日期选择器传入后端获得数据*/
    handleDateChange(){
      if(this.queryParams.userId != null){
        this.queryParams.date = this.valueDate
        this.getAll()
      }else {
        alert("请选择用户");
      }
    },
    getAll(){
      if(this.queryParams.date === null){
        const end = new Date();
        const start = new Date(new Date().getFullYear(), 0);
        const formatDate = (date) => {
          const year = date.getFullYear();
          const month = String(date.getMonth() + 1).padStart(2, '0');
          const day = String(date.getDate()).padStart(2, '0');
          return `${year}-${month}-${day}`;
        };
        this.queryParams.date = [formatDate(start), formatDate(end)];
      }
      listGetAll(this.queryParams).then(response => {
        // 新增排序逻辑
        const sortedData = response.sort((a, b) =>
          new Date(a.date) - new Date(b.date)
        );

        this.all.date = sortedData.map(item => {
          const dt = new Date(item.date);
          return `${dt.getFullYear()}-${(dt.getMonth()+1).toString().padStart(2,'0')}-${dt.getDate().toString().padStart(2,'0')} ` +
            `${dt.getHours().toString().padStart(2,'0')}:${dt.getMinutes().toString().padStart(2,'0')}:${dt.getSeconds().toString().padStart(2,'0')}`;
        });

        this.all.heartRate = sortedData.map(item => item.heartRate);
        this.all.steps = sortedData.map(item => item.steps);
        this.all.sleepDuration = sortedData.map(item => item.sleepDuration);
        this.total = response.total;
        this.initAll(this.all.date,this.all.heartRate,this.all.steps,this.all.sleepDuration)
        this.loading = false;
      });
    },
    /**获取目标*/
    getGoal(){
      this.loading = true;
      const userId = Number(this.queryParams.userId);

      Promise.all([
        listGetGoal(userId),
        listGetGoal2(userId)
      ]).then(([res1, res2]) => {
        // 合并两个响应结果
        this.tableData = [res1, res2].map(response => ({
          goalId: response.goalId,
          userId: response.userId,
          name: response.name.toString(),
          targetValue: response.targetValue,
          actualValue: response.actualValue,
          status: response.actualValue >= response.targetValue ? '1' : '0',
          date: (() => {
            const d = new Date(response.date);
            return `${d.getFullYear()}-${(d.getMonth()+1).toString().padStart(2,'0')}-${d.getDate().toString().padStart(2,'0')} ` +
              `${d.getHours().toString().padStart(2,'0')}:${d.getMinutes().toString().padStart(2,'0')}:${d.getSeconds().toString().padStart(2,'0')}`;
          })()
        }));
      }).catch(error => {
        console.error('获取目标数据失败:', error);
        this.tableData = []; // 清空数据或显示错误信息
      }).finally(() => {
        this.loading = false;
      });
    },
    getWarning() {
      this.loading = true;
      const userId = Number(this.queryParams.userId);

      listGetWarning(userId).then(response => {
        // 修正数据结构处理
        this.warningTableData = response.rows.map(item => ({
          notifyContent: item.notifyContent
        }));
        console.log('处理后的警告数据:', this.warningTableData);
      }).catch(error => {
        console.error('获取警告数据失败:', error);
        this.warningTableData = []; // 清空数据
        this.$message.error('获取警告数据失败'); // 添加用户提示
      }).finally(() => {
        this.loading = false;
      });
    }
  }
}
</script>
<style scoped>
.all{
  background: linear-gradient(to right, rgba(229, 166, 166, 0.49), #42bade);
  position: absolute;
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
}
.admin{
  position: absolute;
  margin-right: 0;
  margin-left: 97%;
  margin-top: 0.5%;
}
/*----------基础数据----------------------------*/
.base-data{
  height: 25%;
  width: 100%;
  display: flex;
}
.heart{
  display: flex;
  flex-direction: column;
  background-color: rgb(255, 255, 255);
  margin-top: 1%;
  margin-bottom: 1%;
  width: 25%;
  margin-left: 6.25%;
  border-radius: 15px;
  box-shadow: 0 5px 10px rgba(0,0,0,0.5);
}
.echarts-title-icon{
  display: flex;
  width: 100%;
  height:30%;
}
.echarts-title{
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 50%;
  height: 100%;
}
.echarts-title span{
  align-items: center;
  height: 100%;
}
.echarts-icon{
  width: 50%;
  height: 100%;
}
.heart-echarts{
  width: 100%;
  height: 100%;

}
.step{
  display: flex;
  flex-direction: column;
  background-color: rgb(255, 255, 255);
  width: 25%;
  margin: 1% 6.25%;
  border-radius: 15px;
  box-shadow: 0 5px 10px rgba(0,0,0,0.5);
}
.sleep{
  display: flex;
  flex-direction: column;
  background-color: rgb(255, 255, 255);
  margin-top: 1%;
  margin-bottom: 1%;
  width: 25%;
  margin-right: 6.25%;
  border-radius: 15px;
  box-shadow: 0 5px 10px rgba(0,0,0,0.5);
}
/*------------可视化数据图------------------------------*/
.echarts{
  display: flex;
  height: 45%;
  width: 100%;
}
.health{
  background-color: white;
  margin: 1% 1% 1% 6.25%;
  width: 87.5%;
  border-radius: 15px;
  box-shadow: 0 5px 10px rgba(0,0,0,0.5);
  display: flex;
  flex-direction: column;
}
.title-date{
  display: flex;
  width: 100%;
  height: 20%;
}
.health span{
  height: 100%;
  width: 80%;

}
/* 使用 flex 布局实现双向居中 */
.date {
  display: flex;
  justify-content: center; /* 水平居中 */
  align-items: center;     /* 垂直居中 */
  height: 100%;            /* 需要明确高度 */
  width: 100%;             /* 需要明确宽度 */
}

/* 处理 Element UI 的默认样式 */
.date .el-date-picker {
  width: 100%;             /* 继承父容器宽度 */
  max-width: 350px;        /* 防止过宽 */
}

/* 如果父级容器需要高度支持 */
.parent-container {
  height: 100vh;           /* 或使用具体高度值 */
  display: flex;           /* 启用 flex 上下文 */
}
.all-data{
  width: 100%;
  height: 80%;
}
.target{
  background-color: white;
  margin: 1% 6.25% 1% 1%;
  width: 28.5%;
  height: 92%;
  border-radius: 15px;
  box-shadow: 0 5px 10px rgba(0,0,0,0.5);
}
.target-span-state{
  width: 100%;
  height: 100%;
  display: flex;
  overflow: hidden;
}

/*-----------------建议、计划、目标----------------------------*/
.suggest-action-plan{
  height: 30%;
  width: 100%;
  display: flex;
}
.suggestion{
  display: flex;
  flex-direction: column;
  background-color: rgb(255, 255, 255);
  margin-top: 1%;
  margin-bottom: 1%;
  width: 25%;
  margin-left: 6.25%;
  border-radius: 15px;
  box-shadow: 0 5px 10px rgba(0,0,0,0.5);
}
.plan{
  background-color: rgb(255, 255, 255);
  width: 57.5%;
  margin: 1% 6.25% 1% 5%;
  border-radius: 15px;
  box-shadow: 0 5px 10px rgba(0,0,0,0.5);
}



@keyframes changeGradient {
  0% {
    background: linear-gradient(to right, #ffffff, rgba(234, 228, 224, 0.42));
  }
  50% {
    background: linear-gradient(to right, rgba(255, 255, 255, 0.47), #4290de);
  }
  100% {
    background: linear-gradient(to right, #4280de, #424ade);
  }
}

/* 表格行动画 */
.staggered-item {
  opacity: 0;
  transform: translateY(10px);
  animation: fadeInUp 0.5s forwards;
}

@keyframes fadeInUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 列延迟动画 */
.staggered-table .el-table__row td:nth-child(1) .staggered-item {
  animation-delay: 0.2s;
}
.staggered-table .el-table__row td:nth-child(2) .staggered-item {
  animation-delay: 0.4s;
}
.staggered-table .el-table__row td:nth-child(3) .staggered-item {
  animation-delay: 0.6s;
}
.staggered-table .el-table__row td:nth-child(4) .staggered-item {
  animation-delay: 0.8s;
}
.staggered-table .el-table__row td:nth-child(5) .staggered-item {
  animation-delay: 1s;
}
.staggered-table .el-table__row td:nth-child(6) .staggered-item {
  animation-delay: 1.2s;
}
.staggered-table + .staggered-item {
  animation-delay: 1.4s; /* 接续最后一列1.2s之后 */
}
/* 对话框入场动画 */
.dialog-animate {
  animation: dialogEnter 0.3s ease-out;
}

@keyframes dialogEnter {
  from {
    transform: scale(0.95);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}
/* 基础入场动画 */
@keyframes sectionEntrance {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 按顺序设置动画延迟 */
/* 修改选择器层级 */
.base-data > .heart {
  animation: sectionEntrance 0.6s ease-out forwards;
  animation-delay: 0.2s;
  opacity: 0;
}

.base-data > .step {
  animation: sectionEntrance 0.6s ease-out forwards;
  animation-delay: 0.4s;
  opacity: 0;
}

.base-data > .sleep {
  animation: sectionEntrance 0.6s ease-out forwards;
  animation-delay: 0.6s;
  opacity: 0;
}

.echarts > .health {
  animation: sectionEntrance 0.6s ease-out forwards;
  animation-delay: 0.8s;
  opacity: 0;
}

.echarts > .target:not(.el-dialog__wrapper) {
  animation: sectionEntrance 0.6s ease-out forwards;
  animation-delay: 1.0s;
  opacity: 0;
}

.suggest-action-plan > .suggestion {
  animation: sectionEntrance 0.6s ease-out forwards;
  animation-delay: 1.2s;
  opacity: 0;
}

.suggest-action-plan > .action {
  animation: sectionEntrance 0.6s ease-out forwards;
  animation-delay: 1.4s;
  opacity: 0;
}

.suggest-action-plan > .plan {
  animation: sectionEntrance 0.6s ease-out forwards;
  animation-delay: 1.6s;
  opacity: 0;
}
/* 修改全局背景样式 */
/* 优化背景流动效果 */
.all {
  background: linear-gradient(
    135deg,
    rgba(225, 240, 255, 0.95) 10%,    /* 冰蓝色 */
    rgba(173, 216, 230, 0.88) 40%,    /* 天蓝色 */
    rgba(240, 248, 255, 0.92) 70%,    /* 雾白色 */
    rgba(135, 206, 235, 0.9) 100%     /* 浅钢蓝 */
  );
  background-size: 300% 300%;
  position: absolute;
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
}

@keyframes gradientFlow {
  0%, 100% {
    background-position: 0% 50%;
    opacity: 0.98;
  }
  33% {
    background-position: 100% 25%;
    opacity: 0.95;
  }
  66% {
    background-position: 50% 75%;
    opacity: 0.97;
  }
}

/* 优化内容区块视觉层次 */
.base-data > div,
.echarts > div,
.suggest-action-plan > div {
  box-shadow: 0 4px 20px rgba(0, 120, 255, 0.08);
}

/* 消息提示动画 */
.message-fade {
  animation: messageMove 0.5s;
}

@keyframes messageMove {
  0% {
    transform: translateY(20px);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}


</style>
